using System;
using System.Linq;
using Amazon.ECS.Model;
using RomanJendrusz.Amazon.ETL.Domain;
using RomanJendrusz.Amazon.ETL.Infrastructure;
using RomanJendrusz.Amazon.ETL.Infrastructure.Loging.Core;
namespace RomanJendrusz.Amazon.ETL.Messages.MessageMappers
{
    public class GetBookDetailsMessageMapper: 
        MessageMapper<GetBookDetailsRequest, ItemLookupRequest, ItemLookupResponse>
    {


        public override AmazonResponse MapToAmazonResponse(ItemLookupResponse awsResponse)
        {
            var bookItem = GetRequestItem(awsResponse, 0);
            if(!bookItem.IsSetItemAttributes())
            {
                throw new InvalidOperationException("There is no item attributes set in the response");
            }
            var attributes = bookItem.ItemAttributes;
            var book = new Book
                           {
                               Asin = AssertThat.IsNotNull(bookItem.ASIN, "ASIN"),
                               DetailPageURL = AssertThat.IsNotNull(bookItem.DetailPageURL, "DetailPageURL"),
                               Binding = AssertThat.IsNotNull(attributes.Binding, "Binding"),
                               EAN = attributes.EAN,
                               //TODO: Zmiana jednostek
                               ISBN = attributes.ISBN,
                               Label = attributes.Label,
                               Manufacturer = attributes.Manufacturer,
                               NumberOfItems = Convert.ToInt32(attributes.NumberOfItems),
                               NumberOfPages = Convert.ToInt32(attributes.NumberOfPages),
                               UPC = attributes.UPC,
                               Title = AssertThat.IsNotNull(attributes.Title, "Title"),
                               Studio = attributes.Studio,
                               Publisher = attributes.Publisher
            };
            if(attributes.PublicationDate == null)
            {
                LogGateway.LogFor(GetType()).Error(string.Format("The item with asin:{0} and title '{1}' is not a book", book.Asin, book.Title));
                return new GetBookDetailsResponse(CorrelationId) { IsValid = true, RetrievedBook = null };
            }
            DateTime date;
            if (DateTime.TryParse(attributes.PublicationDate, out date) == false)
            {
                date = new DateTime(1900, 1,1);
            }
            book.PublicationDate = date;
            if(attributes.IsSetPackageDimensions())
            {
                if(attributes.PackageDimensions.IsSetHeight())
                {
                    book.Height = attributes.PackageDimensions.Height.Value;
                }
                else
                {
                    book.Height = -1;
                }
                if (attributes.PackageDimensions.IsSetLength())
                {
                    book.Length = attributes.PackageDimensions.Length.Value;
                }
                else
                {
                    book.Length = -1;
                }
                if (attributes.PackageDimensions.IsSetWidth())
                {
                    book.Width = attributes.PackageDimensions.Width.Value;
                }
                else
                {
                    book.Width = -1;
                }
                if (attributes.PackageDimensions.IsSetWeight())
                {
                    book.Weight= attributes.PackageDimensions.Weight.Value;
                }
                else
                {
                    book.Weight = -1;
                }                 
            }
            else
            {
                LogGateway.LogFor(GetType()).Error(string.Format("The book with asin: {0} has no package dimension informations", book.Asin));
                book.Height = -1;
                book.Length = -1;
                book.Width = -1;
                book.Weight = -1;
                
            }
            if(attributes.IsSetListPrice())
            {
                book.Price = attributes.ListPrice.Amount;
                book.PriceCurrency = Currency.GetCurrencyFor(attributes.ListPrice.CurrencyCode);
            }
            else
            {
                LogGateway.LogFor(GetType()).Error(string.Format("The book with asin: {0} has no price informations", book.Asin));
                book.Price = -1;
                book.PriceCurrency = Currency.USD;
            }
            
                               
            if(attributes.IsSetLanguageName())
            {
                book.Language = attributes.LanguageName[0];
            }
            if(attributes.IsSetAuthor())
            {
                var groupedAuthors = attributes.Author.GroupBy(a => a);
                foreach (var fullName in groupedAuthors)
                {
                    var author = new Author { FullName = fullName.Key };
                    var bookAuthor = new BookAuthors { Author = author, Book = book };
                    book.BookAuthors.Add(bookAuthor);
                }
            }
            var response = new GetBookDetailsResponse(CorrelationId) {IsValid = true, RetrievedBook = book};
            return response;
        }

        public override ItemLookupRequest MapToAwsRequest(GetBookDetailsRequest request)
        {
            var awsRequest = new ItemLookupRequest {MerchantId = request.MerchantId};
            awsRequest.ItemId.Add(request.Identifier);
            //ASIN for books is equal to ISBN 
            //awsRequest.IdType = request.IdentifierType == BookIdentifierType.ASIN ? "ISBN" : "ASIN";
            //So if the product is not a book an exception will be thrown
            if(request.IdentifierType == BookIdentifierType.ISBN)
            {
                awsRequest.IdType = "ISBN";
                awsRequest.SearchIndex = "Books";
            }
            else
            {
                awsRequest.IdType = "ASIN";
            }
            awsRequest.ResponseGroup.Add(request.ResponseGroup);
            awsRequest.MerchantId = request.MerchantId;
            return awsRequest;
        }
    }
}